package com.jeesite.modules.digitalize.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeesite.modules.digitalize.config.Constants;
import com.jeesite.modules.digitalize.dao.DigitalizeComponentNoteShareDao;
import com.jeesite.modules.digitalize.entity.DigitalizeComponentNote;
import com.jeesite.modules.digitalize.entity.DigitalizeComponentNoteShare;
import com.jeesite.modules.digitalize.entity.dto.digitalizeComponentNote.ShareSetDateDto;
import com.jeesite.modules.digitalize.entity.vo.digitalizeComponentNote.DigitalizeComponentNoteShareDetailVo;
import com.jeesite.modules.digitalize.entity.vo.digitalizeComponentNote.DigitalizeComponentNoteShareVo;
import com.jeesite.modules.digitalize.entity.vo.digitalizeComponentNote.DigitalizeComponentNoteVo;
import com.jeesite.modules.digitalize.entity.vo.digitalizeComponentNote.ShortChainVo;
import com.jeesite.modules.digitalize.util.response.ResultStatusCode;
import com.jeesite.modules.digitalize.util.response.ResultVo;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhaoshuaixiang
 * @date 2023/11/20 11:15
 */
@Service
public class DigitalizeComponentNoteShareService extends ServiceImpl<DigitalizeComponentNoteShareDao, DigitalizeComponentNoteShare> {
    @Resource
    private DigitalizeComponentNoteService digitalizeComponentNoteService;
    @Resource
    private UserService userService;

    /**
     * 视点分享
     *
     * @param id 视点id
     * @return ResultVo
     */
    public ResultVo<ShortChainVo> share(Long id) {
        String shortChain = RandomUtil.randomString(6);
        //判断短链是否存在
        while (this.lambdaQuery().eq(DigitalizeComponentNoteShare::getShortChain, shortChain).count() > 0) {
            shortChain = RandomUtil.randomString(6);
        }
        DigitalizeComponentNoteShare share = new DigitalizeComponentNoteShare()
                .setNoteId(id)
                .setDelStatus(Constants.DEL_STATUA_0)
                .setShortChain(shortChain);
        this.save(share);
        return ResultVo.success(BeanUtil.copyProperties(share, ShortChainVo.class));
    }

    public ResultVo<ShortChainVo> getPwd(Long id) {
        String password = RandomUtil.randomString(4);
        DigitalizeComponentNoteShare noteShare = this.getById(id);
        noteShare.setPassword(password);
        this.updateById(noteShare);
        return ResultVo.success(BeanUtil.copyProperties(noteShare, ShortChainVo.class));
    }

    public ResultVo<ShortChainVo> cancelPwd(Long id) {
        DigitalizeComponentNoteShare noteShare = this.getById(id);
        noteShare.setPassword(null);
        this.lambdaUpdate().set(DigitalizeComponentNoteShare::getPassword, null)
                .eq(DigitalizeComponentNoteShare::getId, id)
                .update(new DigitalizeComponentNoteShare());
        return ResultVo.success(BeanUtil.copyProperties(noteShare, ShortChainVo.class));
    }

    public ResultVo<Object> shareCancel(Long id) {
        this.removeById(id);
        return ResultVo.success();
    }

    public ResultVo<ShortChainVo> setDate(ShareSetDateDto dto) {
        if (dto.getExpirationDate() == null) {
            this.lambdaUpdate()
                    .set(DigitalizeComponentNoteShare::getExpirationDate, null)
                    .eq(DigitalizeComponentNoteShare::getId, dto.getId())
                    .update(new DigitalizeComponentNoteShare());
        } else {
            this.lambdaUpdate()
                    .set(DigitalizeComponentNoteShare::getExpirationDate, dto.getExpirationDate())
                    .eq(DigitalizeComponentNoteShare::getId, dto.getId())
                    .update(new DigitalizeComponentNoteShare());
        }
        DigitalizeComponentNoteShare noteShare = this.getById(dto.getId());
        return ResultVo.success(BeanUtil.copyProperties(noteShare, ShortChainVo.class));
    }

    /**
     * 分享列表
     *
     * @param loginUser 登录用户
     * @return List
     */
    public ResultVo<List<DigitalizeComponentNoteShareVo>> shareList(User loginUser) {
        List<DigitalizeComponentNoteShare> list = this.lambdaQuery().eq(DigitalizeComponentNoteShare::getCreateBy, loginUser.getId())
                .and(e -> e.ge(DigitalizeComponentNoteShare::getExpirationDate, new Date()).or().isNull(DigitalizeComponentNoteShare::getExpirationDate))
                .orderByDesc(DigitalizeComponentNoteShare::getId).list();
        if (CollUtil.isEmpty(list)) {
            return ResultVo.success();
        }
        List<Long> noteIdList = list.stream().map(DigitalizeComponentNoteShare::getNoteId).collect(Collectors.toList());
        List<DigitalizeComponentNote> digitalizeComponentNotes = digitalizeComponentNoteService.listByIds(noteIdList);
        Map<Long, DigitalizeComponentNote> componentNoteMap = digitalizeComponentNotes.stream().collect(Collectors.toMap(DigitalizeComponentNote::getId, Function.identity()));
        List<DigitalizeComponentNoteShareVo> collect = list.stream().map(e -> {
            DigitalizeComponentNoteShareVo vo = BeanUtil.copyProperties(e, DigitalizeComponentNoteShareVo.class);
            DigitalizeComponentNote componentNote = componentNoteMap.get(e.getNoteId());
            if (componentNote != null) {
                vo.setComponentName(componentNote.getComponentName());
                vo.setComponentId(componentNote.getComponentId());
                vo.setProjectId(componentNote.getProjectId());
                vo.setFileType(componentNote.getFileType());
            }
            return vo;
        }).collect(Collectors.toList());
        return ResultVo.success(collect);
    }

    /**
     * 根据短链和密码查询分享
     *
     * @param shortChain 短链
     * @param password   密码
     * @return DigitalizeComponentNoteShareDetailVo
     */
    public ResultVo<DigitalizeComponentNoteShareDetailVo> showShare(String shortChain, String password) {
        DigitalizeComponentNoteShare noteShare = this.lambdaQuery().eq(DigitalizeComponentNoteShare::getShortChain, shortChain).one();
        if (noteShare == null) {
            return ResultVo.failure(ResultStatusCode.SHARE_EXPIRED);
        }
        if (noteShare.getExpirationDate() != null && noteShare.getExpirationDate().before(new Date())) {
            return ResultVo.failure(ResultStatusCode.SHARE_EXPIRED);
        }
        if (StrUtil.isNotBlank(noteShare.getPassword()) && StrUtil.isBlank(password)) {
            return ResultVo.failure(ResultStatusCode.SHARE_NEED_PWD);
        }
        if (password != null && !password.equals(noteShare.getPassword())) {
            return ResultVo.failure(ResultStatusCode.SHARE_PWD_MISTAKE);
        }
        DigitalizeComponentNote note = digitalizeComponentNoteService.getById(noteShare.getNoteId());
        DigitalizeComponentNoteShareDetailVo vo = new DigitalizeComponentNoteShareDetailVo()
                .setId(noteShare.getId())
                .setShortChain(noteShare.getShortChain())
                .setNoteId(noteShare.getNoteId())
                .setExpirationDate(noteShare.getExpirationDate());
        if (note != null) {
            vo.setComponentId(note.getComponentId())
                    .setComponentName(note.getComponentName())
                    .setVersionId(note.getVersionId())
                    .setVersionName(note.getVersionName())
                    .setFileUrl(note.getFileUrl())
                    .setNoteParam(note.getNoteParam())
                    .setProjectId(note.getProjectId())
                    .setFileType(note.getFileType());
            //当前分享视点模型的视点、批注、标签
            List<DigitalizeComponentNote> list = digitalizeComponentNoteService.lambdaQuery().eq(DigitalizeComponentNote::getComponentId, note.getComponentId()).list();
            List<User> userList = userService.findList(new User());
            Map<String, String> userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getUserName));

            List<DigitalizeComponentNoteVo> noteVos = list.stream().map(e ->
                    BeanUtil.copyProperties(e, DigitalizeComponentNoteVo.class).setCreateByName(userMap.getOrDefault(e.getCreateBy(), null))
            ).collect(Collectors.toList());
            Map<Integer, List<DigitalizeComponentNoteVo>> collect = noteVos.stream().collect(Collectors.groupingBy(DigitalizeComponentNoteVo::getNoteType));
            vo.setViewpoints(collect.getOrDefault(0, new ArrayList<>()));
            vo.setNotes(collect.getOrDefault(1, new ArrayList<>()));
            vo.setLabels(collect.getOrDefault(2, new ArrayList<>()));
        }
        return ResultVo.success(vo);
    }
}
